Skip to content

fix(jax): defensive pytree dedup in imaging/interferometer analyses#468

Merged
Jammy2211 merged 1 commit into
mainfrom
feature/release-unblockers
May 29, 2026
Merged

fix(jax): defensive pytree dedup in imaging/interferometer analyses#468
Jammy2211 merged 1 commit into
mainfrom
feature/release-unblockers

Conversation

@Jammy2211
Copy link
Copy Markdown
Collaborator

Summary

Ports the existing defensive registration pattern from `autogalaxy/ellipse/model/analysis.py` to `imaging` and `interferometer` analyses. Without this, `AnalysisImaging.fit_from` re-registers `DatasetModel` with JAX every call, and crashes when a prior code path (PyAutoFit's pytree walker on a graphical / multi-dataset model) has already registered `DatasetModel` via an independent dedup set.

Repro

Discovered on `multi/start_here.py` in autogalaxy_workspace during the 2026.5.29.2 release run:

```
File "autogalaxy/imaging/model/analysis.py", line 152, in fit_from
self._register_fit_imaging_pytrees()
File "autogalaxy/imaging/model/analysis.py", line 221, in _register_fit_imaging_pytrees
register_instance_pytree(DatasetModel)
File "autoarray/abstract_ndarray.py", line 136, in register_instance_pytree
register_pytree_node(cls, flatten, unflatten)
ValueError: Duplicate custom PyTreeDef type registration for <class 'autoarray.dataset.dataset_model.DatasetModel'>.
```

Fix

For both `imaging/model/analysis.py` and `interferometer/model/analysis.py`:

  1. Module-level `FIT*_PYTREES_REGISTERED = False` flag — short-circuits re-entry after the first successful registration.
  2. Try-import `autofit.jax.pytrees._REGISTERED_INSTANCE_CLASSES` and cross-populate autoarray's `_pytree_registered_classes` for `DatasetModel`. This makes `register_instance_pytree`'s existing idempotency guard work across both dedup sets.
  3. Set the flag at the end of the function.

Mirrors the defense in `autogalaxy/ellipse/model/analysis.py` (which solved the same problem for ellipse fits).

Paired with

  • PyAutoLens companion PR (same fix for autolens imaging/interferometer)
  • PyAutoBuild PR (release.yml `run_scripts` env block)

Test plan

  • `pytest test_autogalaxy/imaging/model test_autogalaxy/interferometer/model` — 13 passed (unit tests don't exercise the JAX path — real validation comes from CI run_smoke_tests `multi/start_here.py`)
  • CI on this PR
  • Next `autobuild pre_build` dispatch — `run_smoke_tests autogalaxy_workspace` no longer crashes in `multi/start_here.py` with duplicate-registration

🤖 Generated with Claude Code

`AnalysisImaging._register_fit_imaging_pytrees` and the interferometer
counterpart re-registered ``DatasetModel`` on every ``fit_from`` call
even though autoarray's ``_pytree_registered_classes`` is supposed to
make ``register_instance_pytree`` idempotent. The breakdown surfaced in
the 2026.5.29.2 release on `multi/start_here.py`:

  ValueError: Duplicate custom PyTreeDef type registration for
  <class 'autoarray.dataset.dataset_model.DatasetModel'>.

Root cause: ``autofit.jax.pytrees.register_model`` walks the model and
calls ``register_pytree_node`` for any class it finds (including
``DatasetModel`` when present in the model). It dedupes via its own
``_REGISTERED_INSTANCE_CLASSES`` set, **independent** of autoarray's
``_pytree_registered_classes``. Subsequent
``register_instance_pytree(DatasetModel)`` doesn't find it in
autoarray's set, asks JAX to register again, JAX rejects.

Mirrors the existing defense in ``autogalaxy/ellipse/model/analysis.py``:

* Module-level ``_FIT_*_PYTREES_REGISTERED`` flag — skip re-entry.
* Cross-populate autoarray's set from autofit's so
  ``register_instance_pytree`` short-circuits on classes autofit already
  handled.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@Jammy2211 Jammy2211 merged commit f029ab0 into main May 29, 2026
6 checks passed
@Jammy2211 Jammy2211 deleted the feature/release-unblockers branch May 29, 2026 09:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant